package com.mingserve.raw.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

/**
 * 代理转发API请求
 *
 * @author lvwshuai
 * @date 20241129
 */
@Slf4j
@RequiredArgsConstructor
@RestController
public class ProxyController
{
    @Value("${server.api.url:''}")
    private String serverUrl;
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private final RestTemplate restTemplate;

    /**
     * 代理GET请求
     *
     * @param url   目标 URL 的相对路径，不包括服务器地址部分。
     * @return 返回代理GET请求的响应体
     */
    @GetMapping("/proxy")
    public ResponseEntity<String> proxyGetRequest(@RequestParam("url") String url)
    {
        // 解码 URL
        String decodedUrl = URLDecoder.decode(url, StandardCharsets.UTF_8);
        return proxyRequest(serverUrl + decodedUrl, HttpMethod.GET,  null,null);
    }

    /**
     * 代理PUT请求
     *
     * @param url         目标 URL 的相对路径，不包括服务器地址部分。
     * @param token       Header的Authorization token信息
     * @param requestBody 请求体json格式
     * @return 返回代理PUT请求的响应体
     */
    @PutMapping("/proxy")
    public ResponseEntity<String> proxyPutRequest(@RequestParam("url") String url, @RequestHeader(AUTHORIZATION_HEADER) String token, @RequestBody String requestBody)
    {
        return proxyRequest(serverUrl + url, HttpMethod.PUT, token, requestBody);
    }

    /**
     * 代理POST请求
     *
     * @param url         目标 URL 的相对路径，不包括服务器地址部分。
     * @param token       Header的Authorization token信息
     * @param requestBody 请求体json格式
     * @return 返回代理POST请求的响应体
     */
    @PostMapping("/proxy")
    public ResponseEntity<String> proxyPostRequest(@RequestParam("url") String url, @RequestHeader(AUTHORIZATION_HEADER) String token, @RequestBody String requestBody)
    {
        return proxyRequest(serverUrl + url, HttpMethod.POST, token, requestBody);
    }

    /**
     * 创建包含 JSON 内容类型和可选 Authorization 头的 HttpHeaders 实例。
     *
     * @param token Authorization 令牌，如果存在，将其添加到头中。
     * @return 包含适当头信息的 HttpHeaders 实例。
     */
    private HttpHeaders createHeaders(String token)
    {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (token != null && !token.isEmpty()) {
            headers.set(AUTHORIZATION_HEADER, token);
        }
        return headers;
    }

    /**
     * 通用的代理请求方法，用于通过 RestTemplate 发送 HTTP 请求。
     *
     * @param url         目标 URL。
     * @param method      HTTP 方法 (GET, POST, PUT 等)。
     * @param token       可选的 Authorization 令牌，如果存在，将其添加到头中。
     * @param requestBody 请求体，适用于 POST 和 PUT 请求，如果不需要则为 null。
     * @return 代理请求的响应结果，包含状态码和响应体。
     */
    private ResponseEntity<String> proxyRequest(String url, HttpMethod method, String token, String requestBody)
    {
        HttpHeaders headers = createHeaders(token);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);

        try {
            log.info("Received {} request", url.replace(serverUrl, ""));
            ResponseEntity<String> response = restTemplate.exchange(url, method, requestEntity, String.class);
            return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
        } catch (HttpStatusCodeException ex) {
            log.error("Error occurred during the REST call: {}", ex.getResponseBodyAsString(), ex);
            return ResponseEntity.status(ex.getStatusCode()).body(ex.getResponseBodyAsString());
        } catch (Exception ex) {
            log.error("An unexpected error occurred during the REST call", ex);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error");
        }
    }
}
